package cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.port.adapter.persistence.mybatis;

import cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.domain.model.MessageDeliveryLog;
import org.apache.ibatis.jdbc.SQL;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Base64;
import java.util.Map;
import java.util.Objects;

/**
 * Description: {@link MessageDeliveryLogRepository}Provider
 *
 * @author LiKe
 * @version 1.0.0
 * @date 2020-09-02 21:00
 */
public class MessageDeliveryLogRepositoryProvider extends BaseRepositoryProvider {

    /**
     * Description: Insert Provider
     *
     * @param map 参数 Map
     * @return java.lang.String
     * @author LiKe
     * @date 2020-09-03 10:43:14
     */
    public String insert(Map<String, Object> map) {
        final MessageDeliveryLog entity = (MessageDeliveryLog) map.get(KEY_ENTITY);

        final SQL sql = new SQL();
        sql.INSERT_INTO(MessageDeliveryLogRepository.TABLE_NAME)
                .VALUES(MessageDeliveryLog.FIELD_MESSAGE_ID, getSqlValue(Objects.requireNonNull(entity.getMessageId(), "MessageDeliveryLog#ID cannot be null!")));

        nonNullAnd(entity.getMessage(), () -> sql.VALUES(MessageDeliveryLog.FIELD_MESSAGE, getSqlValue(new String(Base64.getEncoder().encode(entity.getMessage().getBytes())))));
        nonNullAnd(entity.getExchange(), () -> sql.VALUES(MessageDeliveryLog.FIELD_EXCHANGE, getSqlValue(entity.getExchange())));
        nonNullAnd(entity.getRoutingKey(), () -> sql.VALUES(MessageDeliveryLog.FIELD_ROUTING_KEY, getSqlValue(entity.getRoutingKey())));
        nonNullAnd(entity.getStatus(), () -> sql.VALUES(MessageDeliveryLog.FIELD_STATUS, getSqlValue(entity.getStatus())));

        return sql.toString();
    }

    /**
     * Description: Update Provider
     *
     * @param map 参数 Map
     * @return java.lang.String
     * @author LiKe
     * @date 2020-09-03 11:12:41
     */
    public String update(Map<String, Object> map) {
        final MessageDeliveryLog entity = (MessageDeliveryLog) map.get(KEY_ENTITY);
        final String[] updateFields = (String[]) map.get(KEY_UPDATE_FIELDS);

        final SQL sql = new SQL();
        sql.UPDATE(MessageDeliveryLogRepository.TABLE_NAME)
                .VALUES(MessageDeliveryLog.FIELD_MESSAGE_ID, getSqlValue(Objects.requireNonNull(entity.getMessageId(), "MessageDeliveryLog#ID cannot be null!")));

        Arrays.asList(updateFields).forEach(updateField -> {
            try {
                final Method getMethod = entity.getClass().getDeclaredMethod("set" + updateField.substring(0, 1).toUpperCase() + updateField.substring(1));
                final Object value = getMethod.invoke(entity);
                // TODO 简单粗暴的 String.valueOf, 实际应根据类型转换成有语义的字符串
                nonNullAnd(value, () -> sql.VALUES(updateField, getSqlValue(value)));
            } catch (NoSuchMethodException ignored) {

            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException("MyBatis :: " + e.getMessage());
            }
        });

        return sql.toString();
    }

}
